window.onload=function(){
	Controller();
}

function IDHelper(row,column){
	this.row=row;
	this.column=column;
	this.getID=function(x,y){
		return y*column+x;
	}
}

function Controller(){
		var row=15;
		var column=30;
		var board=new BoardCreater().create(column,row);
		board.draw();
		var snake=new SnakeCreator().create(column,row);
		snake.birth();
		var egg=new EggCreator().create(column,row,snake);
		egg.draw();
		var gameoverController=new GameoverController();
		$(window).keydown(function(e){
			var ev=e || window.event;
			var dir = ev.keyCode;
			if(dir==Direction.LEFT||dir==Direction.UP||dir==Direction.RIGHT||dir==Direction.DOWN)
				move(dir);			
		});
		var interval=setInterval(move,500,0);
		function move(dir){
			var next=snake.next(dir);
			if(next.coincide(egg.point)){
				snake.gain(egg.point);
				egg=new EggCreator().create(column,row,snake);
				egg.draw();
			}else{
				snake.move(dir);
				if(gameoverController.isGameover(row,column,snake)){
					gameoverController.gameover(interval);
				}
			}
		}
}

function GameoverController(){
	this.isGameover=function(row,column,snake){
		var head=snake.body[0];
		if(head.x<0||head.x>=column||head.y<0||head.y>=row){
			return true;
		}	
		if(snake.inTail(head)){
			return true;
		}
		return false;
	}
	this.gameover=function(interval){
		alert("Gameover");
		clearInterval(interval);
	}
}

function Point(x,y){
	this.x=x;
	this.y=y;
	this.coincide=function(another){
		if(this.x==another.x&&this.y==another.y)
			return true;
		else
			return false;
	}
}

var Direction={};
Direction.LEFT=37;
Direction.UP=38;
Direction.RIGHT=39;
Direction.DOWN=40;

function Board(column,row,painter){
	this.column=column;
	this.row=row;
	this.painter=painter;
	this.draw=function(){
		this.painter.draw(column,row);		
	}
}

function BoardCreater(){	
	this.create=function(column,row){
		var idHelper=new IDHelper(row,column);
		var painter=new BoardPainter(idHelper);
		return new Board(column,row,painter);
	}
}

function BoardPainter(idHelper){
	this.idHelper=idHelper;
	this.draw=function(column,row){
		for(var i=0;i<row;i++){
			for(var j=0;j<column;j++){
				var ele=document.createElement("div");
				ele.className="box";
				ele.id=idHelper.getID(j,i);
				ele.style.height=25;
				ele.style.width=25;
				ele.style.top=50+25*i;
				ele.style.left=50+25*j;
				$("#content").append(ele);
			}
		}
	}
}

function Egg(point,painter){
	this.point=point;
	this.x=this.point.x;
	this.y=this.point.y;
	this.draw=function(){
		painter.draw(this);
	}
}

function EggPainter(idHelper){
	this.idHelper=idHelper;
	this.draw=function(egg){
		var id=idHelper.getID(egg.x,egg.y);
		document.getElementById(id).className="egg";
	}
}

function EggCreator(){
	this.create=function(column,row,snake){
		var x,y;
		do{
			x=Math.floor(column*Math.random());
			y=Math.floor(row*Math.random());
		}while(snake.inBody(new Point(x,y)));
		var idHelper=new IDHelper(row,column);
		var painter=new EggPainter(idHelper);
		return new Egg(new Point(x,y),painter);
	}
}

function Snake(body,gainPainter,movePainter){
	this.body=body;
	this.gainPainter=gainPainter;
	this.movePainter=movePainter;

	this.move=function(dir){		
		var	oriDir=this.getDirection();
		if(oriDir==dir+2||oriDir==dir-2)
			return;
		if(dir!=Direction.LEFT&&dir!=Direction.UP&&dir!=Direction.RIGHT&&dir!=Direction.DOWN)
			dir=oriDir;
		var last=this.body[this.body.length-1];
		var lastStep=new Point(last.x,last.y);
		for(var i=this.body.length-1;i>0;i--){
			this.body[i].x=this.body[i-1].x;
			this.body[i].y=this.body[i-1].y;
		}
		
		if(dir==Direction.LEFT){
			this.body[0].x=this.body[0].x-1;
			this.body[0].y=this.body[0].y;
		}else if(dir==Direction.UP){
			this.body[0].x=this.body[0].x;
			this.body[0].y=this.body[0].y-1;
		}else if(dir==Direction.RIGHT){
			this.body[0].x=this.body[0].x+1;
			this.body[0].y=this.body[0].y;
		}else if(dir==Direction.DOWN){
			this.body[0].x=this.body[0].x;
			this.body[0].y=this.body[0].y+1;
		}	
		this.movePainter.draw(this,lastStep);
	}


	this.birth=function(){
		this.gainPainter.draw(this);
	}
	

	this.gain=function(point){
		for(var i=this.body.length;i>0;i--){
			this.body[i]=this.body[i-1];
		}
		this.body[0]=point;
		this.gainPainter.draw(this);
	}
	

	this.inTail=function(point){
		for(var i=1;i<this.body.length;i++){
			if(this.body[i].coincide(point))
				return true;
		}
		return false;
	}

	
	this.inBody=function(point){
		for (idx in body){
			if(this.body[idx].coincide(point))
				return true;
		}
		return false;
	}
	

	this.getDirection=function(){
		if(this.body[0].x+1==this.body[1].x&&this.body[0].y==this.body[1].y)
			return Direction.LEFT;
		else if(this.body[0].x==this.body[1].x&&this.body[0].y+1==this.body[1].y)
			return Direction.UP;
		else if(this.body[0].x==this.body[1].x+1&&this.body[0].y==this.body[1].y)
			return Direction.RIGHT;
		else if(this.body[0].x==this.body[1].x&&this.body[0].y==this.body[1].y+1)
			return Direction.DOWN;
	}

	this.next=function(dir){
		if(dir!=Direction.LEFT&&dir!=Direction.UP&&dir!=Direction.RIGHT&&dir!=Direction.DOWN)
			dir=this.getDirection();
		var point;
		if(dir==Direction.LEFT)
			point= new Point(body[0].x-1,body[0].y);
		else if(dir==Direction.UP)
			point= new Point(body[0].x,body[0].y-1);		
		else if(dir==Direction.RIGHT)
			point= new Point(body[0].x+1,body[0].y);
		else if(dir==Direction.DOWN)
			point= new Point(body[0].x,body[0].y+1);
		return point;
	}
	
}

function SnakeCreator(){
	this.create=function(column,row){
		var x=Math.floor(column/2);
		var y=Math.floor(row/2);
		var body=new Array(new Point(x,y),new Point(x,y+1));
		var idHelper=new IDHelper(row,column);
		return new Snake(body,new SnakeGainPainter(idHelper),new SnakeMovePainter(idHelper));
	}
}

function SnakeGainPainter(idHelper){
	this.idHelper=idHelper;
	this.draw=function(snake){
		var body=snake.body;
		for (idx in body){
			var point=body[idx];
			var id=idHelper.getID(point.x,point.y);
			var elem=document.getElementById(id);
			if(elem!=null)
				elem.className="snake";
		}
	}
}

function SnakeMovePainter(idHelper){
	this.idHelper=idHelper;
	this.draw=function(snake,lastStep){
		var body=snake.body;
		for (idx in body){
			var point=body[idx];
			var id=idHelper.getID(point.x,point.y);
			var elem=document.getElementById(id);
			if(elem!=null)
				elem.className="snake";
		}
		var lastId=idHelper.getID(lastStep.x,lastStep.y);
		document.getElementById(lastId).className="box";
	}
}

